home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / qlib205.zip / QLIB.ZIP / SRC / MATH / FTOA.ASM next >
Assembly Source File  |  1997-01-20  |  9KB  |  357 lines

  1. ;included by math_bc.asm and math_wc.asm
  2.  
  3. ;data used is in math_com.asm
  4.  
  5. .code
  6.  
  7. fint macro @@QWORDPTR               ;integrerize float number
  8.     fld     @@QWORDPTR              ;load value to get integer part
  9.     frndint                         ;round to integrer
  10.     fstsw   ax                      ;store flags
  11.     fistp   dptr [result]         ;store (rounded) integrer
  12.     fwait
  13.  
  14.     .if ah & 2  ;mask C1
  15.       mov eax,dptr [result]
  16.       dec eax
  17.     .else
  18.       mov eax,dptr [result]
  19.     .endif
  20. endm
  21.  
  22. frnd macro @@QWORDPTR, @@DIGITS     ;round "dizimas periodicas"
  23.     push eax
  24.     push ebx
  25.     push ecx
  26.     push edx         ;save regs
  27.     mov     edx, @@DIGITS
  28.     inc     edx                     
  29.     callp    _pow,10,edx            ;pow(10, digits+1)
  30.     mov     ecx, eax                ;save power of 10 in ecx
  31.     fld     @@QWORDPTR              ;load value
  32.     fint    @@QWORDPTR              ;integrerize
  33.     mov     dptr [tmpd], eax       ;move integrer to temp buffer
  34.     fisub   dptr [tmpd]            ;subtract whole part
  35.     mov     dptr [tmpd], ecx       ;move power of 10 to temp buffer
  36.     fimul   dptr [tmpd]            ;mul fractional part by power
  37.     fstp    qptr [result]         ;store powered fractional part
  38.     fint    result                ;integrerize powered fractional part
  39.     xor     edx, edx                ;clear edx
  40.     mov     ebx, 10                 ;divide by 10
  41.     div     ebx
  42.     xor     ebx,ebx
  43.     cmp     edx, 9                  ;set ebx to 1 if remainder=9
  44.     sete    bl
  45.     mov     dptr [tmpd], ebx       ;move 1 or 0 to temp buffer
  46.     fild    dptr [tmpd]            ;load it
  47.     mov     dptr [tmpd], ecx       ;move power of 10 to temp buffer
  48.     fidiv   dptr [tmpd]            ;divide 1 or 0 by power of 10
  49.     fstp    qptr [result]         ;store fractional number to add
  50.     fld     @@QWORDPTR              ;reload original value
  51.     fadd    result                ;add 0.0000xxxx1 or not
  52.     fstp    @@QWORDPTR              ;store rounded value
  53.     pop edx
  54.     pop ecx
  55.     pop ebx
  56.     pop eax
  57. endm
  58.  
  59. chk_nan_inf proc private
  60.     ;check for NAN and INF in st
  61.     fxam
  62.     fstsw ax
  63.     ffree st
  64.     fwait
  65.     and ah,1000111b    ;mask C? flags
  66.  
  67.     .if ah == 001b
  68.       callp strcpy,edi,"+NAN"
  69.       mov eax,1
  70.       ret
  71.     .endif
  72.     .if ah == 011b
  73.       callp strcpy,edi,"-NAN"
  74.       mov eax,1
  75.       ret
  76.     .endif
  77.     .if ah == 101b
  78.       callp strcpy,edi,"+INF"
  79.       mov eax,1
  80.       ret
  81.     .endif
  82.     .if ah == 111b
  83.       callp strcpy,edi,"-INF"
  84.       mov eax,1
  85.       ret
  86.     .endif
  87.     xor eax,eax
  88.     ret
  89. chk_nan_inf endp
  90.  
  91. .data
  92. MAX_FTOA real8 +1.0e8
  93. MIN_FTOA real8 -1.0e8
  94.  
  95. .code
  96.  
  97. ftoa proc, a:REAL8, string:dword, decimals:dword
  98.  
  99.     pushad
  100.  
  101.     fld a
  102.     mov edi,string
  103.     call chk_nan_inf
  104.     .if eax
  105.       popad
  106.       mov eax,string
  107.       ret
  108.     .endif
  109.  
  110.     fld a
  111.     fcomp MAX_FTOA
  112.     fstsw ax
  113.     fwait
  114.     sahf
  115.     jbe @f
  116.     jmp _etoa
  117. @@:
  118.     fld a
  119.     fcomp MIN_FTOA
  120.     fstsw ax
  121.     fwait
  122.     sahf
  123.     jae @f
  124.     jmp _etoa
  125. @@:
  126.  
  127.     fldcw rnd_0   ;setup RC
  128.  
  129.     mov     [sign], 0               ;clear sign marker
  130.  
  131.     fint    a                       ;`integrerize' number
  132.     mov     edi, [string]           ;load EDI with string    
  133.  
  134.     cmp     eax, 0                  ;below zero?
  135.     jge     @@FTOAabovezero         ;NO=>goto FTOAabovezero
  136.     mov     [sign], 1               ;negative number
  137.     neg     eax                     ;clear sign bit
  138.     xor bptr[a+7],80h               ;remove sign
  139.     mov     [edi], bptr '-'         ;put minus on start of edi
  140.  
  141. @@FTOAabovezero:
  142.     mov     edx, decimals
  143.     frnd    a , edx                 ;round .499999999 to .5
  144.  
  145.     fint    a                       ;integrerize rounded positive number
  146.     call    nibblecount             ;get # of digits
  147.     inc     ecx                     ;increase (nibblecount returns #-1)
  148.  
  149.     add     edi, ecx                ;add digit count to EDI
  150.     movzx   ebx, bptr sign
  151.     add     edi, ebx                ;if negative one more char is needed
  152.     push    ecx                     ;save for further use
  153.     push    edi                     ;save for further use
  154.  
  155.     mov     bptr [edi], '.'         ;put the point
  156.     dec     edi                     ;decrease
  157.  
  158.     mov     ebx, 10                 ;divider
  159. @@FTOAloop1:
  160.     xor     edx, edx                ;divide eax by 10 until
  161.     div     ebx                     ;ecx decreases from max    
  162.     add     edx, '0'                ;number of digits to 0.
  163.     mov     [edi], bptr dl          ;save number MOD 10+30h
  164.     dec     edi                     ;so it's ASCII code
  165.     dec     ecx                     ;decrease count
  166.     jnz     @@FTOAloop1
  167.  
  168.     pop     edi                     ;restore string pos at point
  169.     pop     ecx                     ;restore digit count
  170.     inc     edi                     ;goto after point
  171.  
  172.     ;*********************** [■FRACTIONAL■] ***********************
  173.  
  174.     mov     ecx, decimals           ;make ECX a count of decimals desired
  175.     .if !ecx
  176.       mov al,'0'
  177.       stosb
  178.       jmp nodec
  179.     .endif
  180.     fint    a                       ;`integrerize' float number
  181.     mov     [tmpd], eax              ;move int number to temp location
  182.     fld     a                       ;load float number
  183.     fisub   dptr [tmpd]              ;subtract whole part so only frac is left
  184.     
  185.     mov     tmpd, 10
  186.     mov     ebx, 10          
  187.  
  188. @@FTOAloop2:
  189.     fimul   dptr [tmpd]              ;multiplicate by 10
  190.     fst     qptr [result]           ;save mul'ed result
  191.     fwait
  192.     fint    result                  ;`integrerize' it
  193.  
  194.     xor     edx, edx                ;clear edx
  195.     div     ebx                     ;divide by 10 and get remainder
  196.  
  197.     add     dl, '0'                 ;add 30h to value
  198.     mov     [edi], bptr dl          ;save on string
  199.  
  200.     inc     edi                     ;increase string index
  201.     dec     ecx                     ;decrease 'precision' counter
  202.     jnz     @@FTOAloop2             
  203.  
  204. nodec:
  205.     ffree   st(0)                   ;kill st(0)
  206.  
  207.     mov     [edi], bptr 0           ;put '\0' at end of string
  208.     xor     eax, eax
  209.  
  210.     fldcw cw_def   ;setup RC to default
  211.     fwait
  212.     popad
  213.     mov eax,string
  214.     ret
  215. ftoa endp
  216.  
  217. .data
  218.   _ws db ?  ;whole part sign
  219.  
  220. .code
  221. etoa proc, a:REAL8, string:dword, decimals:dword
  222.   ;print decimal part then 'e' then exponential part
  223.  
  224.   pushad
  225.  
  226.   fld a
  227.   mov edi,string
  228.   call chk_nan_inf
  229.   .if eax
  230.     popad
  231.     mov eax,string
  232.     ret
  233.   .endif
  234.  
  235. _etoa::
  236.  
  237.   fld a
  238.   ftst         ;cmp with 0.0  ;must account for decimals
  239.   fstsw ax
  240.   ffree st
  241.   fwait
  242.   sahf
  243.   .if zero?
  244.     callp ftoa,a,edi,decimals
  245.     callp strlen,edi
  246.     add edi,eax
  247.     callp strcpy,edi,"e+00"
  248.     popad
  249.     mov eax,string
  250.     ret
  251.   .endif
  252.   mov _ws,0
  253.   .if carry?  ;negative #
  254.     mov _ws,1
  255.     xor bptr[a+7],80h  ;remove sign bit
  256.   .endif
  257.  
  258.   fldcw rnd_dw    ;make sure frndint rounds towards down
  259.   
  260.   callp log10,a   ;get exponent part
  261.   LOADF
  262.   fstp tmpr
  263.   fwait
  264.   frnd tmpr, 1    ;round .9999999 to 1
  265.   fld tmpr
  266.   frndint         ;chop decimal part
  267.   fst tmpr        ;save for later
  268.   fistp tmpw      ;and here trunc.
  269.   fwait
  270.  
  271.   callp pow,ten,tmpr   ;find 10 ** tmp
  272.   LOADF
  273.   fld a
  274.   fxch
  275.   fdivp st(1),st     ;find 'a' / (10 ** tmp) which will leave the dec part
  276.   fstp tmpr          ;save dec part
  277.   fwait
  278.   
  279.   .if _ws  ;put in neg #
  280.     mov al,'-'
  281.     stosb
  282.   .endif
  283.   callp ftoa,tmpr,edi,decimals
  284.   callp strlen,edi
  285.   add edi,eax
  286.  
  287.   fldcw cw_def       ;reset cw
  288.  
  289.   mov al,'e'
  290.   stosb
  291.   mov bx,tmpw
  292.   .if bx & 8000h
  293.     neg bx
  294.     mov al,'-'
  295.     stosb
  296.   .else
  297.     mov al,'+'
  298.     stosb
  299.   .endif
  300.   .if bx<10     ;make sure there are at least 2 digits (as BC)
  301.     mov al,'0'
  302.     stosb
  303.   .endif
  304.   callp num2strs,bx,edi,10
  305.  
  306.   popad
  307.   mov eax,string
  308.  
  309.   ret
  310. etoa endp
  311.  
  312. nibblecount proc private
  313.     push eax
  314.     push ebx
  315.     push edx
  316.  
  317.     xor     ecx, ecx
  318.     mov     ebx, 10
  319.  
  320. @@NCloop:
  321.     xor     edx, edx
  322.     div     ebx
  323.     cmp     eax, 0
  324.     je      @@NCend
  325.     inc     ecx
  326.     jmp     @@NCloop
  327.  
  328. @@NCend:
  329.     pop edx
  330.     pop ebx
  331.     pop eax
  332.     ret
  333. nibblecount endp
  334.  
  335. ;This is not an ANSI C pow (this is an integer POW)
  336.  
  337. _pow PROC private uses ebx ecx edx,a1:dword,a2:dword       ;power(number, power)
  338.   mov ecx, a2
  339.   cmp ecx, 0
  340.   .if carry? || zero?
  341.     mov eax,1
  342.     ret
  343.   .endif
  344.  
  345.   mov ebx, a1
  346.   mov eax, ebx
  347.   xor edx, edx
  348.   jmp start
  349. @@:
  350.   mul ebx
  351. start:
  352.   dec ecx
  353.   jnz @b
  354.   ret
  355. _pow ENDP
  356.  
  357.